package birdry.utils	{
	
	//	birdry.utils.DisplayObjectUtil;
	
	import flash.display.*;
	import flash.events.Event;
	import flash.geom.ColorTransform;
	import flash.text.TextField;
	import flash.geom.Matrix;
	import fl.motion.MatrixTransformer;
	import flash.geom.Rectangle;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import birdry.utils.BitmapUtil;

	public class DisplayObjectUtil	{
		
		public static function replaceBitmap( obj: DisplayObject, transparent:Boolean = false, smoothing:Boolean = false ): void	{
			var container:DisplayObjectContainer = obj.parent as DisplayObjectContainer;
			var depth:int = container.getChildIndex(obj);
			container.removeChild(obj);
			var bd:BitmapData = new BitmapData(obj.width, obj.height, transparent, 0x000000);
			bd.draw(obj);
			var bm:Bitmap = new Bitmap(bd);
			bm.x = obj.x;
			bm.y = obj.y;
			bm.smoothing = smoothing;
			container.addChildAt( bm, depth);
		}
		
		public static function copyObject(origin:Object, target:Object):void	{
			for ( var i:int = origin.numChildren - 1; i >= 0; i-- )	{
				target[origin.getChildAt(i).name] = origin.getChildAt(i);
			}
		}
		
		public static function transformAroundPoint( object:DisplayObject, point:Point, propsObj:Object ): void	{
			var tempX:Number, tempY:Number, negX:int, negY:int;
			var local = object.globalToLocal( object.parent.localToGlobal(point));
			for (var i:String in propsObj)	{
				object[i] = propsObj[i];
			}
			var p:Point = object.parent.globalToLocal( object.localToGlobal(local));
			tempX = object.x + point.x - p.x;
			tempY = object.y + point.y - p.y;
			negX = (tempX < 0) ? -1 : 1;                                  
			negY = (tempY < 0) ? -1 : 1;                                  
			object.x = ((tempX % 1) * negX > 0.5) ? int(tempX) + negX : int(tempX);
			object.y = ((tempY % 1) * negY > 0.5) ? int(tempY) + negY : int(tempY);
		}
		
		public static function mosaicPlay(obj:DisplayObjectContainer, speed:Number = 0.002, from:uint =50, to:uint = 1, complete:Function=null):void	{
			var originBD:Bitmap = BitmapUtil.returnBitmap(obj);
			obj.addEventListener(Event.ENTER_FRAME, onEnter);
			var initFlag:Boolean = true;
			function onEnter( e: Event ): void	{
				if (Math.abs(from - to) < 1)	{
					obj.removeEventListener(Event.ENTER_FRAME, onEnter);
					from = to;
					if(complete != null)	complete();
				}
				DisplayObjectUtil.removeDisplayObject(obj, false);
				from += speed * (to - from);
				var bd:Bitmap = BitmapUtil.returnMosaic(originBD, from);
				obj.addChild(bd);
				if (initFlag)	{
					obj.visible = true;
					initFlag = false;
				}
			}
		}
		
		
		public static function setSize(obj:DisplayObject, width:uint, height:uint, cropFlag:Boolean=false):void	{
			var objRatio:Number = obj.width / obj.height;
			var targetRatio:Number = width / height;
			
			if (objRatio > targetRatio)	{
				if (cropFlag)	{
					obj.width = obj.width * (height / obj.height);
					obj.height = height;
				}	else	{
					obj.height = obj.height * (width / obj.width);
					obj.width = width;
				}
			}	else 	{
				if (cropFlag)	{
					obj.height = obj.height * (width / obj.width);
					obj.width = width;
				}	else	{
					obj.width = obj.width * (height / obj.height);
					obj.height = height;
				}
			}
		}
		
		/**
		 * duplication 구현 - 디스플레이오브젝트를 복제한다
		 * @param	target : DisplayObject
		 */
		public static function cloneDisplayObject(target:*): *		{
			var targetClass:Class = Object(target).constructor;
			var duplicate = new targetClass() 
			duplicate.transform = target.transform;
			duplicate.filters = target.filters;
			duplicate.cacheAsBitmap = target.cacheAsBitmap;
			duplicate.opaqueBackground = target.opaqueBackground;
			if (target.scale9Grid) {
				var rect:Rectangle = target.scale9Grid;
				rect.x /= 20, rect.y /= 20, rect.width /= 20, rect.height /= 20;
				duplicate.scale9Grid = rect;
			}
			if (target is TextField)	{
				TextField(duplicate).type = TextField(target).type;
				TextField(duplicate).selectable = TextField(target).selectable; 
			}
			if (target.hasOwnProperty("numChildren"))			{
				for (var i = target.numChildren-1 ; i > -1 ; i --)				{
					duplicate.addChild(cloneDisplayObject(target.getChildAt(i)));
				}
			}
			return duplicate;
		}
		
		public static function applyColor( obj:DisplayObject, color:uint = 0 ): void	{
			if (color == 0)	{
				obj.transform.colorTransform = new ColorTransform(1, 1, 1, 1, 0, 0, 0, 0);   
			}	else	{
				var _color:ColorTransform = obj.transform.colorTransform;
				_color.color = color;
				obj.transform.colorTransform = _color;
			}
		}
		
		/*************************************************************************
		 * 
		 * 배열안의 디스플레이오브젝트들을 속성 tZ의 크기에 맞춰서 뎁스를 정렬한다.
		 * @param	mcArray	: 디스플레이오브젝트를 포함한 배열
		 * @param	tZ : 정렬의 기준이 될 속성값
		 * 
		 ************************************************************************/
		public static function depthSort(mcArray:Array, tZ:String, order:String = "DOWN"): void	{
			var i:uint;
			var tempArray:Array = [];
			tempArray = mcArray.slice();
			tempArray.sortOn(tZ, Array.DESCENDING | Array.NUMERIC);
			
			if(order == "UP")	tempArray.reverse();
			
			for( i = 0; i < tempArray.length; i++)		{
				Object(tempArray[0].parent).setChildIndex(tempArray[i], i);
			}
		}
		
		
		/*************************************************************************
		 * 
		 * 해당 오브젝트의 Depth를 최상위로 올림
		 * @param	obj	: 오브젝트
		 * 
		 ************************************************************************/
		public static function setDepthUp( obj:* ): void	{
			var container: * = Object(obj.parent);
			container.setChildIndex ( obj , container.numChildren - 1) ;
		}
		
		
		/*************************************************************************
		 * 
		 * 컨테이너에 담긴 택스필드의 mouseEnabled 속성을 적용 시킴;
		 * @param	obj	: 해당컨테이너
		 * 
		 ************************************************************************/
		public static function allMouseEnabled( obj:* , chk:Boolean = false): void		{
			var num = obj.numChildren;
			obj.mouseEnabled = chk;
			var tempObj:Object;
			for (var i:uint = 0; i < num; i++)	{
				tempObj = obj.getChildAt(i);
				if (tempObj is MovieClip )	{
					tempObj.mouseEnabled = chk;
					allMouseEnabled( tempObj, chk );
				}	else if (tempObj is Sprite)	{
					tempObj.mouseEnabled = chk;
				}	else if (tempObj is TextField )	{
					tempObj.mouseEnabled = chk;
				}
			}
		}
		
		/**
		 * 디스플레이오브젝트의 하위자원들까지 모두 삭제한다.
		 * @param	displayObj
		 * @param	removeSelf
		 * true일땐 자신객체까지 삭제하고 false 일땐 하위객체들만 삭제함.
		 */
		public static function allDispose( displayObj:*) : void		{
			if (displayObj is MovieClip)		{
				displayObj.stop();
			}
			else if(displayObj is Sprite)	{
				displayObj.graphics.clear();
			}
			else if (displayObj is TextField)	{
				displayObj.text = "";
			}
			else if(displayObj is Shape)	{
				displayObj.graphics.clear();
			}
			else if (displayObj is Bitmap)	{
				displayObj.bitmapData.dispose();
			}
			else if (displayObj is BitmapData)		{
				displayObj.dispose();
			}
			else if (displayObj is Loader)	{
				displayObj.unload();
			}
			var obj:*;
			if (displayObj is DisplayObjectContainer)	{
				for ( var i:int = 0; i < displayObj.numChildren; ++i )	{
					obj = displayObj.getChildAt(i);
					if (obj != null)	{
						allDispose(obj);
					}
				}
			}
			displayObj = null;
		}
		
		public static function allRemoveChild( displayObj:DisplayObject, removeSelf:Boolean = true ) : void		{
			if (removeSelf)	{
				if (displayObj.parent != null)	{
					DisplayObjectContainer(displayObj).removeChild(displayObj);
				}
			}
			if (displayObj is DisplayObjectContainer)		{
				for ( var i:int = displayObj.numChildren - 1; i >= 0; i-- )	{
					removeDisplayObject(DisplayObject(displayObj.getChildAt(i)), true);
				}
			}
		}
		
		public static function realHitTest(object:DisplayObject, point:Point):Boolean {
			if(object is BitmapData) {
				return (object as BitmapData).hitTest(new Point(0,0), 0, object.globalToLocal(point));
			}
			else {
				if(!object.hitTestPoint(point.x, point.y, true)) {
					return false;
				}
				else {
					var bmapData:BitmapData = new BitmapData(object.width, object.height, true, 0x00000000);
					bmapData.draw(object, new Matrix());
					
					var returnVal:Boolean = bmapData.hitTest(new Point(0,0), 0, object.globalToLocal(point));
					
					bmapData.dispose();
					
					return returnVal;
				}
			}
		}
	}	// class
}	// package